<script setup>
import { ref, onMounted } from 'vue'
import WebUploader from 'webuploader'
import { UploadFilled, Close, VideoPause, VideoPlay } from '@element-plus/icons-vue'
import axios from 'axios'
import { ElMessage } from 'element-plus'

const uploader = ref()
const elUploaderRef = ref()
const showProgress = ref(false)
const progressPercentage = ref({})
const progressStatus = ref({})
const uploadResult = ref([])
const fileMd5 = ref({})
const fileSingleSizeLimit = ref(1024 * 1024 * 1024) // 1024MB

const handleUploadChange = (file, fileList) => {
  // 禁用ElUpload组件的上传，只是使用其UI，所以该事件触发仅有可能是添加文件
  console.log('handleUploadChange', file, fileList)
  if (file.raw.size > fileSingleSizeLimit.value) {
    elUploaderRef.value.handleRemove(file)
    ElMessage.error('File size exceeds the limit of ' + fileSingleSizeLimit.value / 1024 / 1024 + 'MB')
    return
  }
  uploader.value.addFile(file.raw);
  console.log('webuploader files', uploader.value.getFiles())
}

const handleUploadRemove = (file, fileList) => {
  // console.log('handleUploadRemove', file, fileList)
  // uploader.value.removeFile(file.raw, true);


  uploader.value.reset()
  let newFiles = fileList.map(f => f.raw)
  uploader.value.addFiles(newFiles)
  console.log('webuploader files after remove', uploader.value.getFiles());
}

const checkAndUploadFile = async (wuFile) => {
  // 使用md5检查文件是否已经上传过，如果已经上传过则不再上传
  console.log('checkAndUploadFile', wuFile)
  let uid = wuFile.source.uid
  console.log('Starting md5 calculation for file:', wuFile.name)

  uploader.value.md5File(wuFile)
    .progress((percentage) => {
      // TODO WebUploader对新版的Jquery还存在问题，会使得md5File().progress()不会被调用
      // TODO Jquery@2.2.4为测试可用最高版本
      // console.log('md5 progress callback:', percentage)
      progressPercentage.value[uid] = percentage * 100
      if (progressStatus.value[uid] !== 'md5') {
        progressStatus.value[uid] = 'md5'
      }
    })
    .then((val) => {
      console.log('md5', val)
      fileMd5.value[uid] = val
      // 检查文件是否已经上传过
      axios.post('http://localhost:8080/upload/checkFile', {
        filename: wuFile.name,
        md5: val
      }).then(res => {
        if (res.data.code === 0 && res.data.data.exist === true) {
          progressStatus.value[uid] = 'success'
          progressPercentage.value[uid] = 100
          uploadResult.value.push(res.data.data.url)
          wuFile.setStatus('complete')
        } else {
          progressStatus.value[uid] = 'active'
          progressPercentage.value[uid] = 0
          // 上传文件
          uploader.value.upload(wuFile)
        }
      })
    })
}

const startUpload = () => {
  showProgress.value = true
  const wuFiles = uploader.value.getFiles()
  console.log('startUpload', wuFiles)
  if (wuFiles && wuFiles.length > 0) {
    wuFiles.forEach(file => checkAndUploadFile(file))
  }
}

const handlePause = (file) => {
  console.log('handlePause', file)
  const uid = file.raw.uid;
  const wuFile = uploader.value.getFiles().find(f => f.source.uid === uid);
  
  if (!wuFile) return;

  if (progressStatus.value[uid] == 'active') {
    uploader.value.stop(wuFile)
    progressStatus.value[uid] = 'paused'
  } else if (progressStatus.value[uid] != 'md5') {
    uploader.value.upload(wuFile)
    progressStatus.value[uid] = 'active'
  }
}

const resetUpload = () => {
  // 停止上传
  uploader.value.getFiles().forEach(file => uploader.value.cancelFile(file))
  showProgress.value = false
  progressPercentage.value = {}
  progressStatus.value = {}
  fileMd5.value = {}
  elUploaderRef.value.clearFiles()
  uploader.value.reset()
}

const getProgressStatusString = (status) => {
  switch (status) {
    case 'success':
      return '上传成功'
    case 'exception':
      return '上传失败'
    case 'active':
      return '上传中'
    case 'md5':
      return 'MD5计算中'
    case 'paused':
      return '已暂停'
    default:
      return '等待上传'
  }
}

const getProgressStatusProp = (status) => {
  switch (status) {
    case 'success':
      return 'success'
    case 'exception':
      return 'exception'
    case 'warning':
      return 'warning'
    default:
      return ''
  }
}

onMounted(() => {
  const chunkSize = 5242880 // 5MB
  uploader.value = WebUploader.create({
    // swf: '/public/js/Uploader.swf',
    server: 'http://localhost:8080/upload/uploadFile',
    resize: false,
    chunked: true,
    chunkSize: chunkSize,
    chunkRetry: 3,
    chunkRetryDelay: 1000, // unit: ms
    threads: 2,
    fileVal: 'file',
    formData: {
      chunkSize: chunkSize,
      md5: ''
    },
    fileSingleSizeLimit: fileSingleSizeLimit.value, // 1024MB
  })

  uploader.value.on('fileQueued', function (file) {
    console.log('fileQueued', file)
  });

  uploader.value.on('uploadProgress', function (file, percentage) {
    progressPercentage.value[file.source.uid] = percentage * 100
  });

  uploader.value.on('uploadSuccess', function (file, response) {
    progressStatus.value[file.source.uid] = 'success'
    uploadResult.value.push(response.data.url)
    console.log('uploadSuccess', file, response)
  });

  uploader.value.on('uploadError', function (file, reason) {
    progressStatus.value[file.source.uid] = 'exception'
    console.log('uploadError', file, reason)
  });

  uploader.value.on('uploadBeforeSend', function (object, data, headers) {
    console.log('uploadBeforeSend', object, data, headers)
    data.md5 = fileMd5.value[object.file.source.uid]
  });

  // uploader.value.on('uploadComplete', function (file) {
  // });
})
</script>

<template>
  <div>
    <el-upload drag multiple :auto-upload="false" :on-change="handleUploadChange" :on-remove="handleUploadRemove"
      ref="elUploaderRef">
      <el-icon class="el-icon--upload"><upload-filled /></el-icon>
      <div class="el-upload__text">
        Drop file here or <em>click to upload</em>
      </div>
      <template #tip>
        <div class="el-upload__tip">
          Any file with a size less than 1024MB
        </div>
      </template>
      <template #file="{ file }">
        <el-row class="file-item" align="middle">
          <el-col :span="3">
            <el-tooltip :content="file.name" placement="top">
              <span class="file-name">{{ file.name }}</span>
            </el-tooltip>
          </el-col>
          <el-col :span="19">
            <el-progress v-if="showProgress" :percentage="progressPercentage[file.raw.uid]" :stroke-width="12"
              :text-inside="true" :status="getProgressStatusProp(progressStatus[file.raw.uid])" striped-flow striped>
              <span>{{ getProgressStatusString(progressStatus[file.raw.uid]) }}</span>
            </el-progress>
          </el-col>
          <el-col :span="2" style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
            <el-button
              v-if="showProgress && (progressStatus[file.raw.uid] === 'active' || progressStatus[file.raw.uid] === 'paused' || progressStatus[file.raw.uid] === 'exception')"
              :icon="progressStatus[file.raw.uid] === 'active' ? VideoPause : VideoPlay" circle plain class="pause-btn"
              @click.stop="handlePause(file)" style="background: none; border: none; padding: 0; margin: 0 2px;" />
            <el-button :icon="Close" circle plain class="remove-btn"
              @click.stop="$refs.elUploaderRef.handleRemove(file)"
              style="background: none; border: none; padding: 0; margin: 0 2px;" />
          </el-col>
        </el-row>
      </template>
    </el-upload>
    <el-button type="primary" @click="startUpload">开始上传</el-button>
    <el-button @click="resetUpload">重置上传</el-button>
    <div v-if="uploadResult.length > 0">
      <h3>上传结果</h3>
      <ul>
        <li v-for="(url, index) in uploadResult" :key="index">
          <a :href="url" target="_blank">{{ url }}</a>
        </li>
      </ul>
    </div>
  </div>
</template>

<style scoped>
.file-item {
  display: flex;
  align-items: center;
  padding: 8px;
  border-bottom: 1px solid #ebeef5;
  position: relative;
  width: 100%;
}

.file-item:hover .remove-btn,
.file-item:hover .pause-btn {
  display: block;
}

.remove-btn,
.pause-btn {
  display: none;
  position: relative;
  right: 8px;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  outline: none;
}

.remove-btn {
  color: #f56c6c;
}

.pause-btn {
  color: #409eff;
}

.file-name {
  flex: 1;
  margin-right: 16px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}

.progress-bar {
  flex: 2;
  margin-left: 16px;
}

:deep(.el-upload-list__item .el-progress) {
  position: relative;
  top: 0;
}
</style>
